#!/usr/bin/perl
use warnings;
use strict;
use File::stat;
#******************************************************************************
# File: 
#		perl.pl
# Recipe: 8.2
#		Counting Lines( or Paragraphs or Records ) 
# Version:
#		0.1
# Author:
#   	Yubei Zhu
# Mail:
#		yubeizhu@gmail.com
# Created at:
#   	2012-08-21  
# Last Update:
#   	2012-08-21
# License: 
#		GPLv3	
#******************************************************************************


############################### Function Part ################################

sub IsReadableFile
#*****************************************************************************
# PURPOSE: 
#      Testing whether a file is readable
# USAGE:   
#      my $sStatus = IsReadableFile( $sFileName )
# PASSED ARGS:  
#      Scalar: filename
# RETURN ARGS:
# 	   True or false
# $sError - Fail Error Message
#       None
#******************************************************************************
{
	my $sFileName = $_[ 0 ];
	return -f $sFileName and -r _ ? 1 : 0;
}

sub IsStableFile
#*****************************************************************************
# PURPOSE: 
#       Testing whether a file is stable or not
# USAGE:   
#      my $sStatus = IsStableFile( $sFileName )
# PASSED ARGS:  
#      Scalar: filename
# RETURN ARGS:
# 	   True or false
# $sError - Fail Error Message
#       None
#******************************************************************************
{
	my $sFileName = shift;
	my $sAgingSec = $_[ 0 ] || 60;
	
	return time() - stat( $sFileName )->mtime > $sAgingSec ? 1 : 0;
}


sub SimpleLinesCount
#*****************************************************************************
# PURPOSE: 
#      Simplely count lines in a file 
# USAGE:   
#      my $sLineNO = SimpleLinesCount( $sFileName )
# PASSED ARGS:  
#      Scalar: filename
# RETURN ARGS:
# 	   scalar: Line No
# $sError - Fail Error Message
#       None
#******************************************************************************
{
	my ( $sFileName ) = shift;
	return 0 if not IsReadableFile( $sFileName ) or not IsStableFile( $sFileName );

	my $sCount = 0;
	open my $fhIn,"<",	$sFileName or die "Can't open file $sFileName:$!";
	$sCount++ while( <$fhIn> );
	close( $fhIn ) or die "Can't close file $sFileName:$!";

	return $sCount;
}

sub QuickLinesCount
#*****************************************************************************
# PURPOSE: 
#      Count lines in a file in a quicker way 
# USAGE:   
#      my $sLineNO = QuickLinesCount( $sFileName )
# PASSED ARGS:  
#      Scalar: filename
# RETURN ARGS:
# 	   scalar: Line No
# $sError - Fail Error Message
#       None
#******************************************************************************
{
	my ( $sFileName ) = shift;
	return 0 if not IsReadableFile( $sFileName ) or not IsStableFile( $sFileName );
	
	my $sCount = 0;
	open my $fhIn,"<",	$sFileName or die "Can't open file $sFileName:$!";
	$sCount += tr/\n/\n/ while sysread( $fhIn, $_, 2 ** 20 );
	close( $fhIn ) or die "Can't close file $sFileName:$!";

	return $sCount;
}

sub ParagraphsCount
#*****************************************************************************
# PURPOSE: 
#      Count paragraphs in a file 
# USAGE:   
#      my $sParagraphNO = ParagraphsCount( $sFileName )
# PASSED ARGS:  
#      Scalar: filename
# RETURN ARGS:
# 	   scalar: Paragraph No
# $sError - Fail Error Message
#       None
#******************************************************************************
{
	my ( $sFileName ) = shift;
	return 0 if not IsReadableFile( $sFileName ) or not IsStableFile( $sFileName );
	
	my $sCount = 0;
	# Set the seperator of record to be ""
	local $/ = "";
	open my $fhIn,"<",	$sFileName or die "Can't open file $sFileName:$!";
	1 while( <$fhIn> );
	# Build-in var to get record number
	$sCount = $.;
    close( $fhIn ) or die "Can't close file $sFileName:$!";
	return $sCount
}	
	
################################# Main Part ###################################
my $sTestFile = "D:/personal/test2.dat";
my $sCount = SimpleLinesCount( $sTestFile );
print "SimpleLinesCount: $sCount\n";

$sCount = QuickLinesCount( $sTestFile );
print "QuickLinesCount: $sCount\n";

$sCount = ParagraphsCount( $sTestFile );
print "ParagraphsCount: $sCount\n";
